
	//====================================================================================================//
	// Serial Port Programming using Win32 API in C                                                       //
	// (Reads data from serial port)                                                                      //
	//====================================================================================================//
	
	//====================================================================================================//
	// www.xanthium.in										                                              //
	// Copyright (C) 2014 Rahul.S                                                                         //
	//====================================================================================================//
	
	//====================================================================================================//
	// The Program runs on the PC side and uses Win32 API to communicate with the serial port or          //
	// USB2SERIAL board and reads the data from it.                                                       //       
	//----------------------------------------------------------------------------------------------------//
	// Program runs on the PC side (Windows) and receives a string of characters.                         //            
	// Program uses CreateFile() function to open a connection serial port(COMxx).                        //
	// Program then sets the parameters of Serial Comm like Baudrate,Parity,Stop bits in the DCB struct.  //
	// After setting the Time outs,the Program waits for the reception of string of characters by setting-//
	// -up the  WaitCommEvent().                                                                          //
	// When a character is reeived bythe PC UART WaitCommEvent() returns and the received string is read- //
	// -using ReadFile(); function.The characters are then displayed on the Console.                      //
	//----------------------------------------------------------------------------------------------------// 
	// BaudRate     -> 9600                                                                               //
	// Data formt   -> 8 databits,No parity,1 Stop bit (8N1)                                              //
	// Flow Control -> None                                                                               //
	//----------------------------------------------------------------------------------------------------//
	
	
	//====================================================================================================//
	// Compiler/IDE  :	Microsoft Visual Studio Express 2013 for Windows Desktop(Version 12.0)            //
	//               :  gcc 4.8.1 (MinGW)                                                                 //
	//                                                                                                    //
	// Library       :  Win32 API,windows.h,                                                              //
	// Commands      :  gcc -o USB2SERIAL_Read_W32 USB2SERIAL_Read_W32.c                                  //
	// OS            :	Windows(Windows 7)                                                                //
	// Programmer    :	Rahul.S                                                                           //
	// Date	         :	30-November-2014                                                                  //
	//====================================================================================================//

	//====================================================================================================//
	// Sellecting the COM port Number                                                                     //
	//----------------------------------------------------------------------------------------------------//
	// Use "Device Manager" in Windows to find out the COM Port number allotted to USB2SERIAL converter-  // 
	// -in your Computer and substitute in the  "ComPortName[]" array.                                    //
	//                                                                                                    //
	// for eg:-                                                                                           //
	// If your COM port number is COM32 in device manager(will change according to system)                //
	// then                                                                                               //
	//			char   ComPortName[] = "\\\\.\\COM32";                                                    //
	//====================================================================================================//

	#include <Windows.h>
	#include <stdio.h>
  #include "stdlib.h"

  int com_rx(HANDLE hComm,unsigned char *rxbuf);
  int com_tx(HANDLE hComm,unsigned char *txbuf, unsigned char txlen);
  
  unsigned char check_sum(unsigned char * buf, unsigned char len)
  {
    unsigned char i,res=0;
    
    for(i=0;i<len;i++)
    {
      res += buf[i];
    }
    
    return res;
  }
  
	void main(int argc,char *argv[])
		{
		  FILE *fp;
			HANDLE hComm;                          // Handle to the Serial port
			char  ComPortName[16];// = "\\\\.\\COM8";  // Name of the Serial port(May Change) to be opened,
			BOOL  Status;                          // Status of the various operations 
			DWORD dwEventMask;                     // Event mask to trigger
			char  TempChar;                        // Temperory Character
			unsigned char  SerialBuffer[16];               // Buffer Containing Rxed Data
			DWORD NoBytesRead;                     // Bytes read by ReadFile()
			int i = 0;
      int j =0;
      int res = -1;
      char txbuf[256];
      char fpath[256];
      unsigned int offset=0;
      int eof = 0;
      unsigned int size;

      if(argc != 5) 
      {
        res = -1;
        goto arg_err;
			}

      /*
      printf("argv[0]:%s\n",argv[0]);
      printf("argv[1]:%s\n",argv[1]);
      printf("argv[2]:%s\n",argv[2]);
      printf("argv[3]:%s\n",argv[3]);
      printf("argv[4]:%s\n",argv[4]);
      
      */

      if(strcmp(argv[1],"-s") == 0)
      {
        res = 0;
        sprintf(ComPortName,"\\\\.\\COM%d",atoi(argv[2]));
      }
      else if(strcmp(argv[3],"-s") == 0)
      {
        res = 0;
        sprintf(ComPortName,"\\\\.\\COM%d",atoi(argv[4]));
      }
      else
      {
        res = -1;
      }

      if(strcmp(argv[1],"-f") == 0)
      {
        res = 0;
        sprintf(fpath,"%s",argv[2]);
      }
      else if(strcmp(argv[3],"-f") == 0)
      {
        res = 0;
        sprintf(fpath,"%s",argv[4]);
      }
      else
      {
        res = -1;
      }
      
      arg_err:
      if(res == -1)
      {
        printf("\narguments input error,%s -s 8 -f xx.bin",argv[0]);
        printf("\niap exit!\n");
        //_getch();
        return;
      }


      res = -1;
      printf("\n iap start");
			/*---------------------------------- Opening the Serial Port -------------------------------------------*/
			
			hComm = CreateFile( ComPortName,                  // Name of the Port to be Opened
		                        GENERIC_READ | GENERIC_WRITE, // Read/Write Access
								0,                            // No Sharing, ports cant be shared
								NULL,                         // No Security
							    OPEN_EXISTING,                // Open existing port only
		                        0,                            // Non Overlapped I/O
		                        NULL);                        // Null for Comm Devices

			if (hComm == INVALID_HANDLE_VALUE) 
      {   
				printf("\n    Error! - Port %s can't be opened\n", ComPortName);
        goto end;
      }
			else
				printf("\n    Port %s Opened\n ", ComPortName);

			/*------------------------------- Setting the Parameters for the SerialPort ------------------------------*/
			
			DCB dcbSerialParams = { 0 };                         // Initializing DCB structure
			dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

			Status = GetCommState(hComm, &dcbSerialParams);      //retreives  the current settings

			if (Status == FALSE)
				printf("\n    Error! in GetCommState()");

			dcbSerialParams.BaudRate = CBR_9600;      // Setting BaudRate = 9600
			dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8
			dcbSerialParams.StopBits = ONESTOPBIT;    // Setting StopBits = 1
			dcbSerialParams.Parity = NOPARITY;        // Setting Parity = None 

			Status = SetCommState(hComm, &dcbSerialParams);  //Configuring the port according to settings in DCB 

			if (Status == FALSE)
				{
					printf("\n    Error! in Setting DCB Structure");
				}
			else //If Successfull display the contents of the DCB Structure
				{
					printf("\n\n    Setting DCB Structure Successfull\n");
					printf("\n       Baudrate = %d", dcbSerialParams.BaudRate);
					printf("\n       ByteSize = %d", dcbSerialParams.ByteSize);
					printf("\n       StopBits = %d", dcbSerialParams.StopBits);
					printf("\n       Parity   = %d", dcbSerialParams.Parity);
				}

			/*------------------------------------ Setting Timeouts --------------------------------------------------*/
			
			COMMTIMEOUTS timeouts = { 0 };
			timeouts.ReadIntervalTimeout         = 5;
			timeouts.ReadTotalTimeoutConstant    = 150;
			timeouts.ReadTotalTimeoutMultiplier  = 5;
			timeouts.WriteTotalTimeoutConstant   = 50;
			timeouts.WriteTotalTimeoutMultiplier = 5;
			
			if (SetCommTimeouts(hComm, &timeouts) == FALSE)
				printf("\n\n    Error! in Setting Time Outs");
			else
				printf("\n\n    Setting Serial Port Timeouts Successfull");

			/*------------------------------------ Setting Receive Mask ----------------------------------------------*/
			
			Status = SetCommMask(hComm, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception
	
			if (Status == FALSE)
				printf("\n\n    Error! in Setting CommMask");
			else
				printf("\n\n    Setting CommMask successfull");

      printf("\n\n");
      fp = fopen(fpath,"rb");
      if(fp == NULL)
      {
        printf("file open fail!\n\n");
        goto end ;
      }
      printf("iap erase flash...\n\n");

    	if (com_tx(hComm,"\xff\x01\x0f\x01\x00\x00\x11",7) != 0)
      {  
      	printf("\n\n   Error %d in Writing to Serial Port",GetLastError());
        goto end;
      }

    i = com_rx(hComm,SerialBuffer);
    printf("rx:");
  	for (j = 0; j < i-1; j++)		// j < i-1 to remove the dupliated last character
  		printf(" %02x", (unsigned char)SerialBuffer[j]);
    if(i!=8 || SerialBuffer[4]!=0 || SerialBuffer[5]!=0)
    {
      printf("\n\n  erase flash fail,iap exit\n\n");
      goto end;
    }
    else
      printf("\n\n  erase flash ok!\n\n");



      fseek(fp,0L,SEEK_END);  
      size = ftell(fp);  
      fseek(fp,0L,SEEK_SET); 
      printf("bin size:%d",size);
      do{
        for(i=0;i<128;i++)
        {
          txbuf[9+i] = fgetc(fp);
          if( feof(fp) )
          { 
              eof = 1;
              break ;
          }
        }
        #if 0
        for(;i<128;i++)
        {
          txbuf[9+i] = 0xff;
        }
        #endif
        #if 1
        txbuf[0]=0xff;
        txbuf[1]=0x01;
        txbuf[2]=0x0f;
        txbuf[3]=0x02;
        txbuf[4]=i;
        txbuf[5]=offset>>24;
        txbuf[6]=offset>>16;
        txbuf[7]=offset>>8;
        txbuf[8]=offset;
        txbuf[9+i] = check_sum(&txbuf[1], i+8);
        offset += i;

        printf("tx:");
        int n=0;
        for(n=0;n<10+i;n++)
          printf(" %02x",(unsigned char)txbuf[n]);
        printf("\n");

    		if (com_tx(hComm,txbuf,n) != 0)
        {  
    			printf("\n\n   Error %d in Writing to Serial Port",GetLastError());
          break;
        }

        i = com_rx(hComm,SerialBuffer);
        printf("rx:");
  	    for (j = 0; j < i-1; j++)		// j < i-1 to remove the dupliated last character
  		  printf(" %02x", (unsigned char)SerialBuffer[j]);
        if(i!=8 || SerialBuffer[4]!=0 || SerialBuffer[5]!=0)
        {
          printf("\n\nerror,iap exit\n\n");
          break;
        }
        else 
        {
          printf("  rx ok");
          if(eof)
            res = 0;
        }

        printf("\n\n");
        #endif
        
      }while(!eof);
      if(res != 0)
        goto end;
      printf("tx: ff 01 0f 03 00 00 13");
		
    	if (com_tx(hComm,"\xff\x01\x0f\x03\x00\x00\x13",7) != 0)
      {  
      	printf("\n\n   Error %d in Writing to Serial Port",GetLastError());
        goto end;
      }

      i = com_rx(hComm,SerialBuffer);
      printf("\nrx:");
    	for (j = 0; j < i-1; j++)		// j < i-1 to remove the dupliated last character
    		printf(" %02x", (unsigned char)SerialBuffer[j]);
      if(i!=8 ||  SerialBuffer[2]!=0x8f || SerialBuffer[3]!=0x03 || SerialBuffer[4]!=0 || SerialBuffer[5]!=0)
      {
        printf("\n\niap check error,iap exit\n\n");
        goto end;
      }
      else
        printf("\n\niap flash check ok!\n\n");
      
      printf("iap success, reboot mcu......");

    	if (com_tx(hComm,"\xff\x01\x00\x07\x00\x78\x80",7) != 0)
      {  
      	printf("\n\n   Error %d in Writing to Serial Port",GetLastError());
        goto end;
      }
      Sleep(100);

end:
				CloseHandle(hComm);//Closing the Serial Port
				printf("\niap exit!\n");
				//_getch();
		}//End of Main()

int com_rx(HANDLE hComm,unsigned char *rxbuf)
{
    //printf("\n\n    Waiting for Data Reception");
  BOOL Status;
  DWORD NoBytesRead;                     // Bytes read by ReadFile()
  DWORD dwEventMask;                     // Event mask to trigger
  char  TempChar;                        // Temperory Character
  int i = 0;

  
  Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
  	
  /*-------------------------- Program will Wait here till a Character is received ------------------------*/				

  if (Status == FALSE)
  {
    printf("\n    Error! in Setting WaitCommEvent()");
  }
  else //If  WaitCommEvent()==True Read the RXed data using ReadFile();
  {
    i = 0;
    //printf("\n\n    Characters Received");
    do
    {
      Status = ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL);
      rxbuf[i] = TempChar;
      i++;
    }
    while (NoBytesRead > 0);
  }

  return i;
}

int com_tx(HANDLE hComm,unsigned char *txbuf, unsigned char txlen)
{
  BOOL Status;
  int ret = 0;
  
  Status = WriteFile(hComm,               // Handle to the Serialport
						   txbuf,            // Data to be written to the port 
						   txlen,   // No of bytes to write into the port
						   NULL,  // No of bytes written to the port
						   NULL);
		
  if (Status != TRUE)
    ret = -1;

  return ret;
}